<?php

namespace Admin\Controller;

use Core\Constant;
use Core\Controller\AdminBaseController;
use Core\Exception\BusinessException;
use Core\Helper\ApplicationDirectoryHelper;
use Core\Session\AdminSessionHelper;
use Exception;
use Model\Page;
use Zend\Json\Json;
use Zend\View\Model\JsonModel;
use Zend\View\Model\ViewModel;

class PageController extends AdminBaseController {

    public function indexAction() {

        $templateTable = $this->getTableFinder()->getTemplateTable(
            AdminSessionHelper::getCurrentLang()
        );
        $allTemplates = $templateTable->getAll();
        return array('allTemplates'=>$allTemplates);
    }

    public function listAction()
    {

        try{
            $module = $this->params()->fromPost('mymodule');
            $controller = $this->params()->fromPost('mycontroller');
            $template = $this->params()->fromPost('mytemplate');
            $name = $this->params()->fromPost('name');
            $pageTable = $this->getTableFinder()->getPageTable();

            $searchOption = array();
            $searchOption['module'] = $module;
            $searchOption['controller'] = $controller;
            $searchOption['template'] = $template;
            $searchOption['name'] = $name;

            $sortData = $this->params()->fromPost("sort");
            if($sortData){
                $order = array();
                foreach ($sortData as $sortField) {
                    $field = $sortField['field'];
                    $direction = $sortField['dir'];
                    $orderClause = $field." ".$direction;
                    array_push($order, $orderClause);
                }
            }else{
                $order = array("id desc");
            }

            $page = $this->params()->fromPost("page");
            $rows = $this->params()->fromPost("pageSize");
            $offset = ($page - 1) * $rows;
            $allPages = $pageTable->search(true, $offset, $rows, $order,$searchOption);
            return new JsonModel(array('success'=>true,
                'rows'=>$allPages["rows"]->toArray(),
            'total'=>$allPages["total"]));

        }catch(Exception $e){
            $this->fireExceptionEvent($e, \Core\Constant::$EVENT_NAME_ADMIN_EXCEPTION);
            return $this->genJsonErrorView($e);
        }
    }

    public function removeAction(){
        try{

            $pageId = $this->params()->fromPost('id');
            if(!$pageId)
                throw new BusinessException("Page not found, id: ".$pageId);
            $pageTable = $this->getTableFinder()->getPageTable();
            $pageTable->delete($pageId);
            return new JsonModel(array('success'=>true));

        }catch (Exception $e){
            $this->fireExceptionEvent($e, \Core\Constant::$EVENT_NAME_ADMIN_EXCEPTION);
            return $this->genJsonErrorView($e);
        }
    }

    public function addAction(){
        try{

            $viewModel = new ViewModel();
            $roleTable = $this->getTableFinder()->getRoleTable();
            $allRoles = $roleTable->getAll();
            $viewModel->setVariable('allRoles', $allRoles);

            $templateTable = $this->getTableFinder()->getTemplateTable(
                AdminSessionHelper::getCurrentLang()
            );
            $allTemplates = $templateTable->getAll();
            $viewModel->setVariable('allTemplates', $allTemplates);

            $viewModel->setVariable('treeData', Json::encode($this->getBlockInstanceTreeData()));

            return $viewModel;

        }catch(Exception $e){
            $this->fireExceptionEvent($e, \Core\Constant::$EVENT_NAME_ADMIN_EXCEPTION);
            return $this->genJsonErrorView($e);
        }
    }

    private function getBlockInstanceTreeData(){
        $blockClassTable = $this->getTableFinder()->getBlockClassTable();

        $resultArr = array();
        $allBlockClass = $blockClassTable->getAll();
        $tmp = 0;
        foreach ($allBlockClass as $blockClassItem) {
            if($tmp == 0)
                $isExpanded = true;
            else
                $isExpanded = false;

            $allBlockInstances = $blockClassItem->getAllBlockInstance();
            $blockInstanceArr = array();
            foreach ($allBlockInstances as $blockInstanceItem) {
                array_push($blockInstanceArr, array('id'=>$blockInstanceItem->id,
                    'text'=>$blockInstanceItem->name
                ));
            }
            array_push($resultArr, array('id'=>$blockClassItem->id,
                'text'=>$blockClassItem->name, 'expanded'=>$isExpanded,
                'items'=>$blockInstanceArr));
            $tmp++;
        }
        return $resultArr;
    }

    public function findScriptAction()
    {
        try{
            $viewModel = new ViewModel();
            $viewModel->setTerminal(true);

            $module =  $this->params()->fromPost('myModule');
            $controller =  $this->params()->fromPost('myController');
            $action =  $this->params()->fromPost('myAction');
            $pageId =  $this->params()->fromPost('pageId');
            $pageTable = $this->getTableFinder()->getPageTable();
            $page_Item = null;
            if($pageId){
                $page_Item = $pageTable->getPage($pageId);
            }

            ApplicationDirectoryHelper::prepareViewScript($module, $controller, $action);

            $viewModel->setVariable('viewScriptFile', $action . '.php');
            $viewModel->setVariable('pageItem' , $page_Item);

            return $viewModel;

        }catch(Exception $e){
            $this->fireExceptionEvent($e, \Core\Constant::$EVENT_NAME_ADMIN_EXCEPTION);
            return $this->genErrorView($e);
        }

    }

    public function savePageAction()
    {
        try{
            $params = $this->params();
            if($params->fromPost("pageId")){
                $this->updatePage($params);
                return new JsonModel(array('success'=>true,"pageId"=>$params->fromPost("pageId")));
            }

            $route = $params->fromPost("route");

            $routeService = $this->getTableFinder()->getRouteTable(
                AdminSessionHelper::getCurrentLang()
            );
            $aRoute = $routeService->getRouteByRoute($route);
            if( $aRoute)
                throw new  BusinessException("Url đã tồn tại!");

            $blockInstanceIds = $params->fromPost("blockInstanceIds");


            //add privilege
            $privilegeService = $this->getTableFinder()->getPrivilegeTable();
            $privilegeTypeService = $this->getTableFinder()->getPrivilegeTypeTable();
            $privilegeType_Item = $privilegeTypeService->
                getPrivilegeTypeByCode(Constant::$PRIVILEGE_TYPE_ACCESS_PAGE_CODE);

            $privilegeId = $privilegeService->insert(array("type_id" => $privilegeType_Item->id,
                "code" => $params->fromPost("privilegeCode"),
                "name" => "Quyền truy cập trang" . " " . $params->fromPost("route")));

            //attach privilege to role
            $privilege_Item = $privilegeService->getPrivilege($privilegeId);
            if(!$params->fromPost("isPublishToAll")){
                $allRole = $params->fromPost("accessRoles");
                foreach ($allRole as $roleId) {
                    $privilege_Item->updateRole($roleId,true);
                }
            }

            //add page
            $pageService = $this->getTableFinder()->getPageTable();


            $module = $params->fromPost("myModule");
            $controller = $params->fromPost("myController");
            $action  = $params->fromPost("myAction");
            //
            $allParamDefs = $params->fromPost('paraDefs');

            $paramArr = array();
            $paramString = '';
            if($allParamDefs ){
                foreach ($allParamDefs as $aDef) {
                    $tmpArr = explode('$$$',$aDef);
                    $paramArr[$tmpArr[0]] = $tmpArr[1];
                }
                $paramString = Json::encode($paramArr);
            }


            $pageId = $pageService->insert(array("name" => $params->fromPost("name"),
                "title" => $params->fromPost("title"),'params'=>$paramString,
                "summary" => $params->fromPost("description"), "template_id" => $params->fromPost("templateId")
                , "privilege_id" => $privilegeId,"is_publish_for_all" => $params->fromPost("isPublishToAll"),
                "module" => $module, "controller" => $controller, "action" => $action));

            //add page block
            $page_Item = $pageService->getPage($pageId);
            if($blockInstanceIds){
                foreach ($blockInstanceIds as $item) {
                    $pieces = explode("$$$", $item);
                    $page_Item->addBlock($pieces[0],$pieces[1]);
                }
            }


            //add route
            $routeTable = $this->getTableFinder()->getRouteTable(
                AdminSessionHelper::getCurrentLang()
            );

            $routeTable->insert(array("page_id"=>$pageId,"route"=>$route,
                "name"=>$params->fromPost("name"), "lang"=>AdminSessionHelper::getCurrentLang()));

            return new JsonModel(array('success'=>true,"pageId"=>$pageId));


        } catch(Exception $e){
            $this->fireExceptionEvent($e, \Core\Constant::$EVENT_NAME_ADMIN_EXCEPTION);
            return $this->genJsonErrorView($e);
        }
    }

    // long running task without transaction guarantee
    private function updatePage($params){

        $params = $this->params();
        $pageId = $params->fromPost("pageId");
        $pageService = $this->getTableFinder()->getPageTable();

        $page_Item = $pageService->getPage($pageId);
        if(!$page_Item instanceof Page) throw new BusinessException("Page Id không hợp lệ.");

        //update route
        $route = $params->fromPost("route");
        $routeService = $this->getTableFinder()->getRouteTable(
            AdminSessionHelper::getCurrentLang()
        );

        $aRoute = $routeService->getRouteByRoute($route);

        if( $aRoute && $page_Item->getRoute()->id != $aRoute->id)
            throw new  BusinessException("Url đã tồn tại!");

        $page_Item->updateRoute($route, $params->fromPost("name"));
        //update privilege
        $privilegeCode = $params->fromPost("privilegeCode");
        $page_Item->updatePrivilege($privilegeCode);
        //attach privilege to role
        $privilegeService = $this->getTableFinder()->getPrivilegeTable();
        $privilege_Item = $privilegeService->getPrivilege($page_Item->privilege_id);
        $privilege_Item->detachAllRole();
        if(!$params->fromPost("isPublishToAll")){
            $allRole = $params->fromPost("accessRoles");
            foreach ($allRole as $roleId) {
                $privilege_Item->updateRole($roleId,true);
            }
        }

        $page_Item->detachAllBlock();
        $blockInstanceIds = $params->fromPost("blockInstanceIds");
        if($blockInstanceIds){
            foreach ($blockInstanceIds as $item) {
                $pieces = explode("$$$", $item);
                $page_Item->addBlock($pieces[0],$pieces[1]);
            }
        }
        //update Page
        $module = $params->fromPost("myModule");
        $controller = $params->fromPost("myController");
        $action  = $params->fromPost("myAction");

        $allParamDefs = $params->fromPost('paraDefs');

        $paramArr = array();
        if($allParamDefs)
        foreach ($allParamDefs as $aDef) {
            $tmpArr = explode('$$$',$aDef);
            $paramArr[$tmpArr[0]] = $tmpArr[1];
        }

        $paramString = Json::encode($paramArr);
        $pageService->update(array( "name" => $params->fromPost("name"), "title" => $params->fromPost("title"),
            "summary" => $params->fromPost("description"), "template_id" => $params->fromPost("templateId")
            ,'params'=>$paramString,"is_publish_for_all" => $params->fromPost("isPublishToAll"),
            "module" => $module,"controller" => $controller, "action" => $action), $pageId);
    }

    public function checkRouteExistsAction(){
        try{
            $route = $this->params()->fromPost("route");
            $routeTable = $this->getTableFinder()->getRouteTable(
                AdminSessionHelper::getCurrentLang()
            );
            $result = $routeTable->getRouteByRoute($route);
            if($result)
                return new JsonModel(array('success'=>true,'exists'=>true));
            else
                return new JsonModel(array('success'=>true,'exists'=>false));

        }catch (Exception $e){
            $this->fireExceptionEvent($e, \Core\Constant::$EVENT_NAME_ADMIN_EXCEPTION);
            return $this->genJsonErrorView($e);
        }
    }

    public  function getParameterBoxAction(){
        $url = $this->params()->fromPost('url');
        $id = $this->params()->fromPost('id');
        $pageItem = null;
        if($id) {
            $pageItem = $this->getTableFinder()->getPageTable()->getPage($id);

        }

        $tmpArr = explode(':',$url);
        unset($tmpArr[0]);
        $paramArr = array();
        foreach ($tmpArr as $aChunk) {
            if($aChunk){
                $dumpArr = explode('/',$aChunk);
                array_push($paramArr, $dumpArr[0]);
            }
        }
        $viewModel = new ViewModel(array('paramArr' => $paramArr, 'pageItem'=>$pageItem));
        $viewModel->setTerminal(true);
        return $viewModel;
    }

    public function editAction(){
        try{
            $viewModel = new ViewModel();
            $roleTable = $this->getTableFinder()->getRoleTable();
            $allRoles = $roleTable->getAll();
            $viewModel->setVariable('allRoles',$allRoles);

            $templateTable = $this->getTableFinder()->getTemplateTable(
                AdminSessionHelper::getCurrentLang()
            );
            $allTemplates = $templateTable->getAll();
            $viewModel->setVariable('allTemplates',$allTemplates);

            $id = $this->params()->fromQuery("id");


            if(!$id) throw new BusinessException("Page id null");

            $pageTable = $this->getTableFinder()->getPageTable();
            $page_Item = $pageTable->getPage($id);

            $viewModel->setVariable('pageItem', $page_Item);
            $viewModel->setVariable('treeData', Json::encode($this->getBlockInstanceTreeData()));

            return $viewModel;
        }catch(Exception $e){
            $this->fireExceptionEvent($e, \Core\Constant::$EVENT_NAME_ADMIN_EXCEPTION);
            return $this->genErrorView($e);
        }

    }


    public function editPageAction(){
        $templateId = $this->params()->fromQuery('templateId');
        $module = $this->params()->fromQuery('mymodule');
        $controller = $this->params()->fromQuery('mycontroller');
        $action = $this->params()->fromQuery('myaction');
        $this->layout('page_edit_layout.php');

        $templateTable = $this->getTableFinder()->getTemplateTable(
            AdminSessionHelper::getCurrentLang());
        $templateItem = $templateTable->getTemplate($templateId);
        $templateFile = $templateItem->file_name;

        ApplicationDirectoryHelper::prepareViewScript($module, $controller, $action);
        return new ViewModel(array('templateFile'=>$templateFile,'viewScriptFile'=> $action . '.php'));
    }
}